#include "dispatcher_manager.h"

namespace application {
namespace dispatcher {

DispatcherManager::DispatcherManager(
    std::shared_ptr<vehicle::VehicleService> vehicleService,
    std::shared_ptr<MapApplicationService> mapService,
    std::shared_ptr<kernel::ILogger> logger, QObject* parent)
    : QObject(parent),
      m_vehicleService(std::move(vehicleService)),
      m_mapService(std::move(mapService)),
      m_logger(std::move(logger)) {
  // 连接地图加载信号，动态创建调度器
  if (m_mapService) {
    connect(m_mapService.get(), &MapApplicationService::floorMapLoaded, this,
            &DispatcherManager::onFloorMapLoaded);
  }
}

void DispatcherManager::init() {
  if (m_logger) {
    m_logger->info(
        "DispatcherManager initialized, waiting for map load signals");
  }

  // 检查是否有已加载的地图，为它们创建调度器
  if (m_mapService) {
    auto floors = m_mapService->getLoadedFloors();
    for (int floor : floors) {
      // 尝试为已加载的地图创建调度器
      onFloorMapLoaded(floor);
    }
  }
}

void DispatcherManager::onFloorMapLoaded(int floor) {
  if (!m_mapService) {
    if (m_logger) {
      m_logger->error("DispatcherManager: MapService not available");
    }
    return;
  }

  // 如果该楼层已有调度器，跳过
  if (m_dispatchers.contains(floor)) {
    if (m_logger) {
      m_logger->debug(
          QString("DispatcherManager: Dispatcher already exists for floor %1")
              .arg(floor));
    }
    return;
  }

  // 检查地图服务是否存在
  auto mapSvc = m_mapService->getMapByFloor(floor);
  if (!mapSvc) {
    if (m_logger) {
      m_logger->warning(
          QString("DispatcherManager: MapService not available for floor %1")
              .arg(floor));
    }
    return;
  }

  // 检查地图名称
  const QString mapName = m_mapService->getMapNameForFloor(floor);
  if (mapName.isEmpty()) {
    if (m_logger) {
      m_logger->warning(
          QString("DispatcherManager: Map name is empty for floor %1")
              .arg(floor));
    }
    return;
  }

  // 创建调度器
  auto* disp = new RouteDispatcher(mapName, floor, m_vehicleService,
                                   m_mapService, m_logger, this);
  disp->init();
  if (m_dispatchCallback) {
    disp->setDispatchCallback(m_dispatchCallback);
  }
  if (m_solveFailureCallback) {
    disp->setSolveFailureCallback(m_solveFailureCallback);
  }
  m_dispatchers.insert(floor, disp);

  if (m_logger) {
    m_logger->info(
        QString("DispatcherManager: Created dispatcher for floor %1 (map: %2)")
            .arg(floor)
            .arg(mapName));
  }
}

RouteDispatcher* DispatcherManager::getDispatcher(int floor) const {
  return m_dispatchers.value(floor, nullptr);
}

TaskPublishHandle DispatcherManager::stationTaskFromServer(
    const QString& station, int floor, const QString& operation,
    std::function<void()> cb) {
  auto* d = getDispatcher(floor);
  if (!d) return {TaskFunction::FuncMove, -1, MoveFunctionStatus::MoveError};
  return d->stationTaskFromServer(station, operation, std::move(cb));
}

TaskPublishHandle DispatcherManager::stationTaskFromServer(
    int agvNumber, const QString& station, int floor, const QString& operation,
    std::function<void()> cb) {
  auto* d = getDispatcher(floor);
  if (!d) {
    if (m_logger) {
      m_logger->error(QString("No dispatcher found for floor %1 (AGV%2 -> %3)")
                          .arg(floor)
                          .arg(agvNumber)
                          .arg(station));
    }
    return {TaskFunction::FuncMove, -1, MoveFunctionStatus::MoveError};
  }
  return d->stationTaskFromServer(agvNumber, station, operation, std::move(cb));
}

void DispatcherManager::setDispatchCallback(
    std::function<void(int, const QList<QString>&)> cb) {
  m_dispatchCallback = std::move(cb);
  for (auto it = m_dispatchers.begin(); it != m_dispatchers.end(); ++it) {
    if (auto* dispatcher = it.value()) {
      dispatcher->setDispatchCallback(m_dispatchCallback);
    }
  }
}

void DispatcherManager::setSolveFailureCallback(std::function<void(const QString&)> cb) {
  m_solveFailureCallback = std::move(cb);
  for (auto it = m_dispatchers.begin(); it != m_dispatchers.end(); ++it) {
    if (auto* dispatcher = it.value()) {
      dispatcher->setSolveFailureCallback(m_solveFailureCallback);
    }
  }
}

void DispatcherManager::cancelPendingForAgv(int agvNumber)
{
  for (auto it = m_dispatchers.begin(); it != m_dispatchers.end(); ++it) {
    if (auto* dispatcher = it.value()) {
      dispatcher->cancelPendingForAgv(agvNumber);
    }
  }
}

}  // namespace dispatcher

}  // namespace application
